using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
using TALoaders;
using TAAlert.CommonUtils;
using TAAlert.BackTest;
using TAAlert.Charting;

namespace TAAlert.GUI
{
    public partial class StrategyDetailsGUI : Form
    {
        static private readonly TraceSwitch traceM = new TraceSwitch("StrategyDetails", "Debug info for StrategyDetails GUI class");
        private StrategyName strategyM;
        private StrategyParameters paramsM;

        /// <summary>Constructor</summary>
        /// <param name="strategy">Strategy name</param>
        public StrategyDetailsGUI(StrategyName strategy)
        {
            this.strategyM = strategy;
            InitializeComponent();
            // Form Header
            this.Text = strategy.ToString() + " Strategy Details";
            gbStrategyParametersM.Text = strategy.ToString() + " Strategy Parameters";
            // Add available loaders
            foreach (string loaderName in Enum.GetNames(typeof(Loader)))
                this.cbLoaderM.Items.Add(loaderName);
            this.cbLoaderM.SelectedIndex = (int)Loader.Yahoo;
            // Signal Quote Types:
            this.cbSigQuoteTypeM.Items.Add(QuoteType.AdjClose.ToString());
            this.cbSigQuoteTypeM.SelectedIndex = 0;
            this.cbSigQuoteTypeM.Items.Add(QuoteType.AvgHL.ToString());
            this.cbSigQuoteTypeM.Items.Add(QuoteType.AvgHLC.ToString());
            // Disable action buttons before DataTable is loaded
            this.btChartM.Enabled = false;
            this.btToExcelM.Enabled = false;

            // Strategy Parameters
            this.txtTransactionCostM.Text = Convert.ToString(0.003);
            this.txtVolTM.Text = Convert.ToString(0.30);
            switch (this.strategyM)
            {
                case StrategyName.VEMA:
                    // ToolTips
                    ToolTip volToolTip = new ToolTip();
                    volToolTip.SetToolTip(this.txtVolTM, "Set treashold volatility. For volatilites below this value nEMA1 is used. For folatilites above the treshold the nEMA2 is used");
                    break;
                case StrategyName.EMA:
                    lbNEma2M.Visible = false;
                    lbVolatilityM.Visible = false;
                    txtNEma2M.Visible = false;
                    txtVolTM.Visible = false;
                    lbnEMA1M.Text = "nEMA:";
                    break;
                case StrategyName.TwoEMA:
                    lbnEMA1M.Text = "nShort:";
                    lbNEma2M.Text = "nLong:";
                    break;
                case StrategyName.MACD:
                    lbnEMA1M.Text = "nShort:";
                    lbNEma2M.Text = "nLong:";
                    lbVolatilityM.Text = "nFast:";
                    txtNEma1M.Text = "12";
                    txtNEma2M.Text = "26";
                    txtVolTM.Text = "9";
                    break;
                default:
                    string errMessage = "Strategy " + strategy.ToString() + " not supported so far";
                    MessageBox.Show(errMessage, "UNSUPPORTED Feature", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    break;
            }
            this.dgViewM.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableAlwaysIncludeHeaderText;
        }

        private void cbLoaderM_SelectedIndexChanged(object sender, EventArgs e)
        {
            this.cbTickerM.Items.Clear();
            string[] tickers = DownloaderFactory.getDefaultTickers(this.cbLoaderM.SelectedItem.ToString());

            foreach (string ticker in tickers)
                this.cbTickerM.Items.Add(ticker);
            this.cbTickerM.SelectedIndex = 0;
        }

        private struct StrategyParameters
        {
            public string loaderName;
            public string ticker;
            public DateTime startDate;
            public DateTime endDate;
            public QuoteType sigType;
            public int n1;
            public int n2;
            public double volT;
            public double transCost;
            public override string ToString()
            {
                return "loaderName=" + loaderName + ", ticker=" + ticker + ", start=" + startDate.ToShortDateString() + ", end=" + endDate.ToShortDateString() +
                    ", sigType=" + sigType.ToString() + ", n1=" + n1 + ", n2=" + n2 + ", volT=" + volT + ", transCost=" + transCost;
            }
        }
        // Load data to DataTable and show it in GridView
        private void btLoadM_Click(object sender, EventArgs e)
        {
            Debug.WriteLineIf(traceM.TraceInfo, "StrategyDetailsGUI: Load button clicked...");
            this.paramsM.loaderName = this.cbLoaderM.SelectedItem.ToString();
            this.paramsM.ticker = cbTickerM.Text;
            this.paramsM.startDate = this.dtStartDateM.Value.Date;
            this.paramsM.endDate = this.dtEndDateM.Value.Date;
            this.paramsM.sigType = (QuoteType)Enum.Parse(typeof(QuoteType), cbSigQuoteTypeM.SelectedItem.ToString());

            if (Int32.TryParse(this.txtNEma1M.Text, out this.paramsM.n1) &&
                Int32.TryParse(this.txtNEma2M.Text, out this.paramsM.n2) &&
                Double.TryParse(this.txtVolTM.Text, out this.paramsM.volT) &&
                Double.TryParse(this.txtTransactionCostM.Text, out this.paramsM.transCost))
            {
                Debug.WriteLineIf(traceM.TraceInfo, this.paramsM.ToString());
                StrategyDetail strategyDetail = new StrategyDetail(this.paramsM.loaderName, this.paramsM.ticker, this.paramsM.startDate, this.paramsM.endDate, this.paramsM.transCost, this.paramsM.sigType);
                DataTable dTable;
                switch (this.strategyM)
                {
                    case StrategyName.VEMA:
                        dTable = strategyDetail.generateVEMATable(this.paramsM.n1, this.paramsM.n2, this.paramsM.volT);
                        break;
                    case StrategyName.EMA:
                        dTable = strategyDetail.generateEMATable(this.paramsM.n1);
                        break;
                    case StrategyName.TwoEMA:
                        dTable = strategyDetail.generateTwoEmaTable(this.paramsM.n1, this.paramsM.n2, this.paramsM.volT);
                        break;
                    case StrategyName.MACD:
                        dTable = strategyDetail.generateMACDTable(this.paramsM.n1, this.paramsM.n2, Convert.ToInt32(this.paramsM.volT));
                        break;
                    default:
                        throw new Exception("Strategy " + this.strategyM.ToString() + "is not supported yet");
                }

                // Set the DataSource
                this.dgViewM.DataSource = dTable;
                // Format columns
                for (int ix = 0; ix < dTable.Columns.Count; ++ix)
                {
                    DataGridViewColumn col = this.dgViewM.Columns[ix];
                    col.DefaultCellStyle.Format = (string)dTable.Columns[ix].ExtendedProperties[StrategyDetail.FORMAT_EXT_PROPERTY];
                }
                // Enable other actions
                this.btChartM.Enabled = true;
                this.btToExcelM.Enabled = true;
            }
            else
            {
                Debug.WriteLineIf(traceM.TraceWarning, "Parsing failed....");
                Debug.WriteLineIf(traceM.TraceWarning, "Int32.TryParse(this.txtNEma1M.Text, out this.paramsM.n1)=" + Int32.TryParse(this.txtNEma1M.Text, out this.paramsM.n1));
                Debug.WriteLineIf(traceM.TraceWarning, "Int32.TryParse(this.txtNEma2M.Text, out this.paramsM.n2)=" + Int32.TryParse(this.txtNEma2M.Text, out this.paramsM.n2));
                Debug.WriteLineIf(traceM.TraceWarning, "Double.TryParse(this.txtVolTM.Text, out this.paramsM.volT)=" + Double.TryParse(this.txtVolTM.Text, out this.paramsM.volT));
                Debug.WriteLineIf(traceM.TraceWarning, "Double.TryParse(this.txtTransactionCostM.Text, out this.paramsM.transCost)=" + Double.TryParse(this.txtTransactionCostM.Text, out this.paramsM.transCost));
            }
        }

        // Save DataTable to CSV file
        private void saveToExcel(object sender, EventArgs e)
        {
            Debug.WriteLine(traceM.TraceInfo, "saveToExcel called...");
            
            SaveFileDialog dlg = new SaveFileDialog();
            dlg.DefaultExt = ".csv";
            dlg.Filter = "Alert files (*.csv)|*.csv";
            if (dlg.ShowDialog() == DialogResult.OK)
            {
                DataTable dTable = (DataTable)this.dgViewM.DataSource;
                string fileName = dlg.FileName;
                Utilities.saveDataTableToCSV(fileName, dTable);
                Debug.WriteLineIf(traceM.TraceInfo, " saved to " + fileName);
            }
            else
                Debug.WriteLineIf(traceM.TraceInfo, " NOT SAVED!!");
        }

        // Show DataTable in a chart
        private void createChart(object sender, EventArgs e)
        {
            DataTable dTable = (DataTable)this.dgViewM.DataSource;
            string ticker = this.paramsM.ticker;

            StrategyChartGUI chart = new StrategyChartGUI(ticker, this.strategyM, this.paramsM.sigType, dTable);

            switch (this.strategyM)
            {
                case StrategyName.VEMA:
                    chart.createVEMACharts(this.paramsM.n1, this.paramsM.n2);
                     break;
                case StrategyName.EMA:
                    chart.createEMACharts(this.paramsM.n1);
                    break;
                case StrategyName.TwoEMA:
                    chart.createTwoEMACharts(this.paramsM.n1, this.paramsM.n2);
                    break;
                case StrategyName.MACD:
                    chart.createMACDCharts();
                    break;
                default:
                    MessageBox.Show("Charting not implemented for " + strategyM.ToString(), "WARNING", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    return;
            }

            chart.Show();
        }
    }
}